package se.lcsmerge.util;

import java.util.Vector;

import se.lcsmerge.data.FileDataDTO;
/**
 * 
 * @author caucse06 SE Team
 *
 */
public class LCSCompareImpl implements LCSCompare {
	
	private int[][] lcs;         
 
	private Vector<FileDataDTO> modifyLeftFile; 
	private Vector<FileDataDTO> modifyRightFile;
	private Vector<FileDataDTO> leftFile; 
	private Vector<FileDataDTO> rightFile;
	private Vector<FileDataDTO> tempLeft;
	private Vector<FileDataDTO> tempRight;
	private Vector<FileDataDTO> tempVector;
	
//	private Vector<Integer> lcsFlag;	
//	private Vector<Integer> leftFlag;
//	private Vector<Integer> rightFlag;
	
	private int leftCount = 0;
	private int rightCount = 0;
	private int leftPointer;
	private int rightPointer;
	
	public int getLeftCount(){
		return leftCount; 
	}
	public int getRightCount(){
		return rightCount; 
	}
	
	public void incLeftCount(){
		leftCount++;
	}

	public void incRightCount(){
		rightCount++;
	}

	public void setLeftCount(int a){
		leftCount = a;
	}
	public void setRightCount(int a){
		rightCount = a;
	}
	

	
	@Override
	public void init(Vector<FileDataDTO> left, Vector<FileDataDTO> right){
		leftFile = new Vector<FileDataDTO>();
		leftFile = left;
		rightFile = new Vector<FileDataDTO>();
		rightFile = right;
		modifyLeftFile = new Vector<FileDataDTO>();
		modifyRightFile = new Vector<FileDataDTO>();
		tempLeft = new Vector<FileDataDTO>();
		tempRight = new Vector<FileDataDTO>();
//		leftFile.trimToSize();
//		rightFile.trimToSize();
		boolean isChange = false;
		

		

		
		if(leftFile.size()<rightFile.size()){
			tempVector = new Vector<FileDataDTO>();
			tempVector = leftFile;
			leftFile = rightFile;
			rightFile = tempVector;
			
			isChange = true;
		}
		
		lcs = new int[leftFile.size()+1][rightFile.size()+1];	
		
		leftPointer = leftFile.size();
		rightPointer = rightFile.size();
		
		makeLcs();
		/*
		for(int i=0; i<=leftFile.size(); i++){
			for(int j = 0 ; j<=rightFile.size(); j++){
				System.out.print(lcs[i][j] + " ");
			}
			System.out.println();
		}
		*/

		
		makeModifyFile(leftFile.size(), rightFile.size());
		
		if(isChange){
			tempVector = new Vector<FileDataDTO>();
			tempVector = modifyLeftFile;
			modifyLeftFile = modifyRightFile;
			modifyRightFile = tempVector;
		}

			
	}
	
	@Override
	public Vector<FileDataDTO> getLeft(){
		return modifyLeftFile;
	}
	
	@Override
	public Vector<FileDataDTO> getRight(){
		return modifyRightFile;
	}
	
	//lcsMake  
	public void makeLcs(){
		

		for(int i=0;i<=leftFile.size();i++){
			lcs[i][0] = 0;			
		}
		for(int j=0;j<=rightFile.size();j++){
			lcs[0][j] =0;			
		}

		for(int i=1;i<=leftFile.size();i++){
			for(int j=1;j<=rightFile.size();j++){
				if(leftFile.elementAt(i-1).getString().equals(rightFile.elementAt(j-1).getString())){ 
					lcs[i][j] = lcs[i-1][j-1] +1; 				
				}
				else{
					lcs[i][j] = Math.max(lcs[i][j-1], lcs[i-1][j]);
				}				
			}				
		}
	}
	
	
	
	public void makeModifyFile(int i, int j){

		String blank = " ";
		

	
		if(lcs[leftFile.size()-1][rightFile.size()-1]==0){
			if(leftFile.size() > rightFile.size()){
				for(int k=0 ; k<leftFile.size() ; k++ ){
					FileDataDTO leftTemp = new FileDataDTO();
					leftTemp = leftFile.elementAt(k);
					leftTemp.setColor(0);
					modifyLeftFile.add(leftTemp);
				}
				for(int k=0 ; k<leftFile.size() ; k++ ){
					if(k<rightFile.size()){
						FileDataDTO rightTemp = new FileDataDTO();
						rightTemp = rightFile.elementAt(k);
						rightTemp.setColor(0);
						modifyRightFile.add(rightTemp);
					}
					else{
						FileDataDTO rightTemp = new FileDataDTO();
						rightTemp.setString(blank);
						rightTemp.setColor(1);
						modifyRightFile.add(rightTemp);						
					}
				}
			}else{
				for(int k=0 ; k<rightFile.size() ; k++ ){
					FileDataDTO rightTemp = new FileDataDTO();
					rightTemp = rightFile.elementAt(k);
					rightTemp.setColor(0);
					modifyRightFile.add(rightTemp);
				}
				for(int k=0 ; k<rightFile.size() ; k++ ){
					if(k<leftFile.size()){
						FileDataDTO leftTemp = new FileDataDTO();
						leftTemp = leftFile.elementAt(k);
						leftTemp.setColor(0);
						modifyLeftFile.add(leftTemp);
					}
					else{
						FileDataDTO leftTemp = new FileDataDTO();
						leftTemp.setString(blank);
						leftTemp.setColor(1);
						modifyLeftFile.add(leftTemp);						
						
					}
				}				
			}
			return;
		}
		
		
		
		
		if(i==0){
			if(rightCount!=0){
				for(;rightCount>0;rightCount--){
					if(rightCount>rightPointer){
						FileDataDTO dto = new FileDataDTO();
						dto.setString(blank);
						dto.setColor(1);
						modifyRightFile.add(0,dto);
					}else{
						FileDataDTO dto = new FileDataDTO();
						dto.setString(rightFile.elementAt(rightCount-1).getString());
						dto.setColor(0);
						modifyRightFile.add(0,dto);
						
					}
					
					FileDataDTO left = new FileDataDTO();
					left.setString(rightFile.elementAt(leftCount-1).getString());
					left.setColor(0);
					modifyLeftFile.add(0,left);
				
				}
				return;
				

			}else{
				for(;j>0;j--){
					FileDataDTO dto = new FileDataDTO();
					dto.setString(blank);
					dto.setColor(1);
					modifyLeftFile.add(0,dto);
					
					FileDataDTO right = new FileDataDTO();
					right.setString(rightFile.elementAt(j-1).getString());
					right.setColor(0);
					modifyRightFile.add(0,right);
				}

			}
			return;
		
			
		}
		
		if(j==0){
			if(leftCount!=0){
				for(;leftCount>0;leftCount--){
					if(leftCount>leftPointer){
						FileDataDTO dto = new FileDataDTO();
						dto.setString(blank);
						dto.setColor(1);
						modifyLeftFile.add(0,dto);
					}else{
						FileDataDTO dto = new FileDataDTO();
						dto.setString(leftFile.elementAt(leftCount-1).getString());
						dto.setColor(0);
						modifyLeftFile.add(0,dto);
						
					}
					
					FileDataDTO right = new FileDataDTO();
					right.setString(rightFile.elementAt(leftCount-1).getString());
					right.setColor(0);
					modifyRightFile.add(0,right);
				
				}
				

			}else{
				for(;i>0;i--){
					FileDataDTO dto = new FileDataDTO();
					dto.setString(blank);
					dto.setColor(1);
					modifyRightFile.add(0,dto);
					
					FileDataDTO left = new FileDataDTO();
					left.setString(leftFile.elementAt(i-1).getString());
					left.setColor(0);
					modifyLeftFile.add(0,left);
				}

			}
			return;
		}	
			
	
		
		
		if(i==0 && j==0) return; 					//when arriving (0,0), terminate.


		
		
		
		if(leftFile.elementAt(i-1).getString().equals(rightFile.elementAt(j-1).getString())){
	//	if(lcs[i][j]>lcs[i][j-1] && lcs[i][j]>lcs[i-1][j] ){
						

			int count = getLeftCount()-getRightCount();
			if(count > 0){
				for(int k=0; k<count ; k++){
					FileDataDTO dto = new FileDataDTO();
					dto.setString(blank);
					dto.setColor(1);
					modifyLeftFile.add(0,dto);				
				}
			}else if(count < 0){
				count = Math.abs(count);
				for(int k=0; k<count ; k++){
					FileDataDTO dto = new FileDataDTO();
					dto.setString(blank);
					dto.setColor(1);			
					modifyRightFile.add(0,dto);				
				}			
			}
	
			for(int k=0; k<tempLeft.size(); k++){
				modifyLeftFile.add(0,tempLeft.elementAt(k));
				

			}

			for(int k=0; k<tempRight.size(); k++){
				modifyRightFile.add(0,tempRight.elementAt(k));
				
				
			}

			
			FileDataDTO left = new FileDataDTO();
			left.setString(leftFile.elementAt(i-1).getString());
			left.setColor(2);
			
			leftPointer--;
			modifyLeftFile.add(0,left);		

		
			
			FileDataDTO right = new FileDataDTO();
			right.setString(rightFile.elementAt(j-1).getString());
			right.setColor(2);
			
			rightPointer--;
			modifyRightFile.add(0,right);

			
			setLeftCount(0);
			setRightCount(0);			
			tempRight.clear();
			tempLeft.clear();
	
	
			makeModifyFile(i-1, j-1);		     

			
		}
		else if(lcs[i][j-1] >= lcs[i-1][j]){ //left
			tempRight.add(rightFile.elementAt(j-1));

			rightPointer--;
			
			incLeftCount();
			makeModifyFile(i, j-1);
			
		}
		else{ //up
			tempLeft.add(leftFile.elementAt(i-1));

			leftPointer--;
			
			incRightCount();			
			makeModifyFile(i-1,j);
		}		
	
	}
	//for Testing
	public int lcsTest(int i, int j){
		return lcs[i][j];
	}
	
	public Vector<FileDataDTO> getModifyLeftFile(){
		return  modifyLeftFile;
	}
	public Vector<FileDataDTO> getModifyRightFile(){
		return  modifyRightFile;
	}
	
	
	
}
